package com.aivin.leakcanarysample;

import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
import android.os.Handler;
import com.aivin.leakcanarysample.bean.MyWeakReference;
import com.aivin.leakcanarysample.tool.SharkTool;
import com.aivin.leakcanarysample.tool.WkLog;
import java.lang.ref.ReferenceQueue;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class MyAppLifecycleHandler implements Application.ActivityLifecycleCallbacks {
    public void onActivityStarted(Activity activity) {  }
    public void onActivityResumed(Activity activity) {   }
    public void onActivityPaused(Activity activity) {  }
    public void onActivityStopped(Activity activity) {   }
    public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {  }

    @Override
    public void onActivityCreated(Activity activity, Bundle bundle) {
        WkLog.showMsg("onActivityCreated: " + activity.getClass().getName());
    }

    @Override
    public void onActivityDestroyed(Activity activity) {
        WkLog.showMsg("监测到Activity销毁:" + activity.getClass().getName());
        WkLog.showMsg("将延时5秒进行泄漏检测...");

        String key = UUID.randomUUID().toString();
        MyWeakReference myWeakReference = new MyWeakReference(activity, referenceQueue);
        myWeakReference.key = key;
        myWeakReference.info = "跟踪对象为=" + activity.getClass().getName();
        leakMap.put(key, myWeakReference); // 等会要用来判断是已经被回收

        handler.postDelayed(() -> watchActivity(myWeakReference), 5000);
    }

    private SharkTool sharkTool = new SharkTool();
    private Handler handler = new Handler();
    private ReferenceQueue referenceQueue = new ReferenceQueue();
    private Map<String, Object> leakMap = new HashMap<>();

    private void watchActivity(MyWeakReference myWeakReference) {
        WkLog.showMsg("泄漏检测开始，" + myWeakReference.info);
        removeWeaklyReachableObjects();

        boolean isRecycled = !leakMap.containsKey(myWeakReference.key);
        if (isRecycled) {
            WkLog.showMsg("通过 ReferenceQueue 判断，已经被回收：" + myWeakReference.info);
        } else {
            WkLog.showMsg("通过 ReferenceQueue 判断 ，还未被回收，执行手动 gc，强制回收：" + myWeakReference.info);
            WkLog.showMsg("leakMap.size="+leakMap.size());
            runGC();

            removeWeaklyReachableObjects();
            WkLog.showMsg("手动 gc 结束 ，再次判断： " + myWeakReference.info);
            boolean isRecycled2 = !leakMap.containsKey(myWeakReference.key);
            WkLog.showMsg("isRecycled2==" + isRecycled2 + "  " + myWeakReference.info);
            WkLog.showMsg("leakMap.size="+leakMap.size());


            String result = sharkTool.watchActivity( ) ;
            WkLog.showMsg("\n分析结果=\n"+ result);
        }
    }

    private void runGC() {
        Runtime.getRuntime().gc();
        try {
            WkLog.showMsg("手动Gc后再等待5秒");
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.runFinalization();
    }


    /**
     * 通过 do ...while 将队列的数据全部取出
     */
    private void removeWeaklyReachableObjects() {
        MyWeakReference myWeakReference;
        do {
            myWeakReference = (MyWeakReference) referenceQueue.poll();
            // 如果 myWeakReference 不为空，说明它包装的对象，已经被系统回收了，然后通知到了这个队列
            if (myWeakReference != null) {
                WkLog.showMsg("已经被回收..." + myWeakReference.info);
                leakMap.remove(myWeakReference.key);
            } else {
                WkLog.showMsg("为空...");
            }
        } while (myWeakReference != null);
    }
}
